// Vector 2d
// (c) jimon game studio

#ifndef JEH_JEVECTOR2D
#define JEH_JEVECTOR2D

#include "jeTypes.h"

namespace je
{
	//! Vector 2d class
	template<typename T>
	class jeVector2d
	{
	public:
		//! Components
		T X,Y;

		//! Constructor
		inline jeVector2d()
			:X(0),Y(0)
		{
		}

		//! Constructor
		inline jeVector2d(T x,T y)
			:X(x),Y(y)
		{
		}

		//! Constructor
		inline jeVector2d(T x)
			:X(x),Y(x)
		{
		}

		//! Flush Vector (set 0,0)
		inline void Flush()
		{
			X = 0;
			Y = 0;
		}

		//! Constructor
		template<typename B>
		inline jeVector2d(const jeVector2d<B> & Other)
			:X((T)Other.X),Y((T)Other.Y)
		{
		}

		//! Set X Y
		inline void SetXY(T x,T y)
		{
			X = x;
			Y = y;
		}

		//! Normalize Vector
		inline jeVector2d<T> & Normalize()
		{
			T DistS = X*X + Y*Y;

			if(DistS == 0)
				return *this;

			DistS = (T) jeInvSqr(DistS);

			X *= DistS;
			Y *= DistS;

			return *this;
		}

		//! operator =
		inline jeVector2d<T> & operator = (const jeVector2d<T> & Other)
		{
			X = Other.X;
			Y = Other.Y;
			return *this;
		}
		
		//! operator =
		template<typename B>
		inline jeVector2d<T> & operator = (const jeVector2d<B> & Other)
		{
			X = (T)Other.X;
			Y = (T)Other.Y;
			return *this;
		}

		//! return true if our vector == other vector
		inline u1 equal(const jeVector2d<T> & Other) const
		{
			if (X == Other.X && Y == Other.Y)
				return true;
			else
				return false;
		}

		//! operator ==
		inline u1 operator == (const jeVector2d<T> & Other) const
		{
			return equal(Other);
		}

		//! operator !=
		inline u1 operator != (const jeVector2d<T> & Other) const
		{
			return !equal(Other);
		}

		//! operator +=
		inline jeVector2d<T> & operator += (const jeVector2d<T> & Other)
		{
			X += Other.X;
			Y += Other.Y;
			return *this;
		}

		//! operator -=
		inline jeVector2d<T> & operator -= (const jeVector2d<T> & Other)
		{
			X -= Other.X;
			Y -= Other.Y;
			return *this;
		}

		//! operator +
		inline jeVector2d<T> operator + (const jeVector2d<T> & Other) const
		{
			return jeVector2d<T>(X + Other.X,Y + Other.Y);
		}
		
		//! operator -
		inline jeVector2d<T> operator - (const jeVector2d<T> & Other) const
		{
			return jeVector2d<T>(X - Other.X,Y - Other.Y);
		}

		//! operator *
		inline jeVector2d<T> operator * (T Value) const
		{
			return jeVector2d<T>(X * Value,Y * Value);
		}

		//! operator /
		inline jeVector2d<T> operator / (T Value) const
		{
			if(Value == 0)
				Value = 0.01f;
			return jeVector2d<T>(X / Value,Y / Value);
		}

		//! operator /
		template<typename B>
		inline jeVector2d<T> operator / (const jeVector2d<B> & Other) const
		{
			jeVector2d<T> Cur;
			if(Other == jeVector2d<T>(0,0))
				Cur = jeVector2d<T>(0.001f,0.001f);
			else
				Cur = Other;
			return jeVector2d<T>(X / Cur.X,Y / Cur.Y);
		}

		//! Get Distance
		f32 GetDistance()
		{
			return jeSqr(X*X+Y*Y);
		}

		//! Get Distance
		f32 GetDistanceQR()
		{
			return X*X+Y*Y;
		}
	};

	//! define float 32 2d vector
	typedef jeVector2d<f32> jeVector2df;

	//! define int 32 2d vector
	typedef jeVector2d<s32> jeVector2di;

};

#endif
